﻿namespace MicroCloud.Extensions
{
    #region "<see cref="ClaimsIdentity"/> 扩展操作类"
    /// <summary>
    /// <see cref="ClaimsIdentity"/> 扩展操作类
    /// </summary>
    public static class ClaimsIdentityExtensions
    {
        #region "扩展方法"
        #region "获取指定类型的用户ID"
        /// <summary>
        /// 获取指定类型的用户ID
        /// </summary>
        /// <typeparam name="T">用户ID类型</typeparam>
        /// <param name="identity">用户身份</param>
        /// <returns>指定类型的用户ID</returns>
        public static T GetUserId<T>(this IIdentity identity)
        {
            Check.NotNull(identity, nameof(identity));
            if (identity is not ClaimsIdentity claimsIdentity)
            {
                return default;
            }
            string value = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            if (value == null)
            {
                return default;
            }
            return value.CastTo<T>();
        }
        #endregion
        #region "获取指定类型的用户ID"
        /// <summary>
        /// 获取指定类型的用户ID
        /// </summary>
        /// <param name="identity">用户身份</param>
        /// <param name="idType">用户ID类型</param>
        /// <returns>指定类型的用户ID</returns>
        public static object GetUserId(this IIdentity identity, Type idType)
        {
            Check.NotNull(identity, nameof(identity));
            if (identity is not ClaimsIdentity claimsIdentity)
            {
                return default;
            }
            string value = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            if (value == null)
            {
                return default;
            }
            return value.CastTo(idType);
        }
        #endregion
        #region "获取字符串类型的用户ID"
        /// <summary>
        /// 获取字符串类型的用户ID
        /// </summary>
        /// <param name="identity">用户身份</param>
        /// <returns>字符串类型的用户ID</returns>
        public static string GetUserId(this IIdentity identity)
        {
            Check.NotNull(identity, nameof(identity));
            if (identity is not ClaimsIdentity claimsIdentity)
            {
                return null;
            }
            return claimsIdentity.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        }
        #endregion

        #region "获取用户名"
        /// <summary>
        /// 获取用户名
        /// </summary>
        /// <param name="identity">用户身份</param>
        /// <returns>用户名</returns>
        public static string GetUserName(this IIdentity identity)
        {
            Check.NotNull(identity, nameof(identity));
            if (identity is not ClaimsIdentity claimsIdentity)
            {
                return null;
            }
            return claimsIdentity.FindFirst(ClaimTypes.Name)?.Value;
        }
        #endregion

        #region "获取用户昵称"
        /// <summary>
        /// 获取用户昵称
        /// </summary>
        /// <param name="identity">用户身份</param>
        /// <returns>用户昵称</returns>
        public static string GetNickName(this IIdentity identity)
        {
            Check.NotNull(identity, nameof(identity));
            if (identity is not ClaimsIdentity claimsIdentity)
            {
                return null;
            }
            return claimsIdentity.FindFirst(ClaimTypes.GivenName)?.Value;
        }
        #endregion
        #region "获取用户Email"
        /// <summary>
        /// 获取用户Email
        /// </summary>
        /// <param name="identity">用户身份</param>
        /// <returns>用户Email</returns>
        public static string GetEmail(this IIdentity identity)
        {
            Check.NotNull(identity, nameof(identity));
            if (identity is not ClaimsIdentity claimsIdentity)
            {
                return null;
            }
            return claimsIdentity.FindFirst(ClaimTypes.Email)?.Value;
        }
        #endregion
        #region "获取用户手机号码"
        /// <summary>
        /// 获取用户手机号码
        /// </summary>
        /// <param name="identity">用户身份</param>
        /// <returns>用户手机号码</returns>
        public static string GetPhoneNumber(this IIdentity identity)
        {
            Check.NotNull(identity, nameof(identity));
            if (identity is not ClaimsIdentity claimsIdentity)
            {
                return null;
            }
            return claimsIdentity.FindFirst(ClaimTypes.MobilePhone)?.Value;
        }
        #endregion

        #region "获取用户所拥有的角色集合"
        /// <summary>
        /// 获取用户所拥有的角色集合
        /// </summary>
        /// <param name="identity">用户身份</param>
        /// <returns>用户所拥有的角色集合</returns>
        public static OnlineRole[] GetRoles(this IIdentity identity)
        {
            Check.NotNull(identity, nameof(identity));
            if (identity is not ClaimsIdentity claimsIdentity)
            {
                return Array.Empty<OnlineRole>();
            }
            //return claimsIdentity.FindAll(ClaimTypes.Role).SelectMany(m =>
            //{
            //    string[] roles = m.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            //    return roles;
            //}).ToArray();
            return claimsIdentity.FindAll(ClaimTypes.Role).SelectMany(m =>
            {
                OnlineRole[] roles = m.Value.IsMissing() ? Array.Empty<OnlineRole>() : m.Value.FromJsonString<OnlineRole[]>();
                return roles;
            }).ToArray();
        }
        #endregion

        #region "获取用户客户端编号"
        /// <summary>
        /// 获取用户客户端编号
        /// </summary>
        /// <param name="identity">用户身份</param>
        /// <returns>用户客户端编号</returns>
        public static string GetClientId(this IIdentity identity)
        {
            Check.NotNull(identity, nameof(identity));
            if (identity is not ClaimsIdentity claimsIdentity)
            {
                return null;
            }
            return claimsIdentity.FindFirst(ClaimTypeConstants.ClientId)?.Value;
        }
        #endregion
        #region "获取用户客户端类型"
        /// <summary>
        /// 获取用户客户端类型
        /// </summary>
        /// <param name="identity">用户身份</param>
        /// <returns>用户客户端类型</returns>
        public static string GetClientType(this IIdentity identity)
        {
            Check.NotNull(identity, nameof(identity));
            if (identity is not ClaimsIdentity claimsIdentity)
            {
                return null;
            }
            return claimsIdentity.FindFirst(ClaimTypeConstants.ClientType)?.Value;
        }
        #endregion

        #region "获取指定类型的用户当前组织机构编号"
        /// <summary>
        /// 获取指定类型的用户当前组织机构编号
        /// </summary>
        /// <typeparam name="T">组织机构编号类型</typeparam>
        /// <param name="identity">用户身份</param>
        /// <returns>指定类型的用户当前组织机构编号</returns>
        public static T GetCurrentOrganizationId<T>(this IIdentity identity)
        {
            var currentOrganizationId = identity.GetCurrentOrganizationId();
            return currentOrganizationId.CastTo<T>(default);
        }
        #endregion
        #region "获取指定类型的用户当前组织机构编号"
        /// <summary>
        /// 获取指定类型的用户当前组织机构编号
        /// </summary>
        /// <param name="identity">用户身份</param>
        /// <param name="idType">组织机构编号类型</param>
        /// <returns>指定类型的用户当前组织机构编号</returns>
        public static object GetCurrentOrganizationId(this IIdentity identity, Type idType)
        {
            var currentOrganizationId = identity.GetCurrentOrganizationId();
            return currentOrganizationId.CastTo(idType, default);
        }
        #endregion
        #region "获取字符串类型的用户当前的组织机构编号"
        /// <summary>
        /// 获取字符串类型的用户当前的组织机构编号
        /// </summary>
        /// <param name="identity">用户身份</param>
        /// <returns>字符串类型的用户当前的组织机构编号</returns>
        public static string GetCurrentOrganizationId(this IIdentity identity)
        {
            Check.NotNull(identity, nameof(identity));
            if (!identity.IsAuthenticated)
            {
                return null;
            }
            if (identity is not ClaimsIdentity claimsIdentity)
            {
                return null;
            }
            var currentOrganizationId = claimsIdentity.GetClaimValueFirstOrDefault(ClaimTypeConstants.CurrentOrganizationId);
            return currentOrganizationId;
        }
        #endregion

        #region "获取指定类型的用户当前部门机构编号"
        /// <summary>
        /// 获取指定类型的用户当前部门机构编号
        /// </summary>
        /// <typeparam name="T">部门机构编号类型</typeparam>
        /// <param name="identity">用户身份</param>
        /// <returns>指定类型的用户当前部门机构编号</returns>
        public static T GetCurrentDepartmentId<T>(this IIdentity identity)
        {
            var currentDepartmentId = identity.GetCurrentDepartmentId();
            return currentDepartmentId.CastTo<T>(default);
        }
        #endregion
        #region "获取指定类型的用户当前部门机构编号"
        /// <summary>
        /// 获取指定类型的用户当前部门机构编号
        /// </summary>
        /// <param name="identity">用户身份</param>
        /// <param name="idType">部门机构编号类型</param>
        /// <returns>指定类型的用户当前部门机构编号</returns>
        public static object GetCurrentDepartmentId(this IIdentity identity, Type idType)
        {
            var currentDepartmentId = identity.GetCurrentDepartmentId();
            return currentDepartmentId.CastTo(idType, default);
        }
        #endregion
        #region "获取字符串类型的用户当前部门机构编号"
        /// <summary>
        /// 获取字符串类型的用户当前部门机构编号
        /// </summary>
        /// <param name="identity">用户身份</param>
        /// <returns>字符串类型的用户当前部门机构编号</returns>
        public static string GetCurrentDepartmentId(this IIdentity identity)
        {
            Check.NotNull(identity, nameof(identity));
            if (!identity.IsAuthenticated)
            {
                return null;
            }
            if (identity is not ClaimsIdentity claimsIdentity)
            {
                return null;
            }
            var currentDepartmentId = claimsIdentity.GetClaimValueFirstOrDefault(ClaimTypeConstants.CurrentDepartmentId);
            return currentDepartmentId;
        }
        #endregion

        #region "获取指定类型的Claim值"
        /// <summary>
        /// 获取指定类型的Claim值
        /// </summary>
        /// <param name="identity">用户身份</param>
        /// <param name="type">Claim值类型</param>
        /// <returns>指定类型的Claim值</returns>
        public static string GetClaimValueFirstOrDefault(this IIdentity identity, string type)
        {
            Check.NotNull(identity, nameof(identity));
            if (identity is not ClaimsIdentity claimsIdentity)
            {
                return null;
            }
            return claimsIdentity.FindFirst(type)?.Value;
        }
        #endregion
        #region "获取指定类型的所有Claim值"
        /// <summary>
        /// 获取指定类型的所有Claim值
        /// </summary>
        /// <param name="identity">用户身份</param>
        /// <param name="type">Claim值类型</param>
        /// <returns>指定类型的所有Claim值</returns>
        public static string[] GetClaimValues(this IIdentity identity, string type)
        {
            Check.NotNull(identity, nameof(identity));
            if (identity is not ClaimsIdentity claimsIdentity)
            {
                return Array.Empty<string>();
            }
            return claimsIdentity.Claims.Where(m => m.Type == type).Select(m => m.Value).ToArray();
        }
        #endregion
        #region "移除指定类型的声明"
        /// <summary>
        /// 移除指定类型的声明
        /// </summary>
        /// <param name="identity">用户身份</param>
        /// <param name="claimType">Claim值类型</param>
        public static void RemoveClaim(this IIdentity identity, string claimType)
        {
            Check.NotNull(identity, nameof(identity));
            if (identity is not ClaimsIdentity claimsIdentity)
            {
                return;
            }
            Claim claim = claimsIdentity.FindFirst(claimType);
            if (claim == null)
            {
                return;
            }
            claimsIdentity.RemoveClaim(claim);
        }
        #endregion
        #region "移除指定类型的所有Claim值"
        /// <summary>
        /// 移除指定类型的所有Claim值
        /// </summary>
        /// <param name="identity">用户身份</param>
        /// <param name="claimType">Claim值类型</param>
        public static void RemoveClaims(this IIdentity identity, string claimType)
        {
            Check.NotNull(identity, nameof(identity));
            if (identity is not ClaimsIdentity claimsIdentity)
            {
                return;
            }
            while (claimsIdentity.HasClaim(o => o.Type == claimType))
            {
                Claim claim = claimsIdentity.FindFirst(claimType);
                if (claim == null)
                {
                    continue;
                }
                claimsIdentity.RemoveClaim(claim);
            }
        }
        #endregion

        #endregion

    }
    #endregion

}
